﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using NPOI.OpenXmlFormats.Spreadsheet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yz.Base;
using Yz.Base.ParaModels;
using Yz.Core.Extensions;
using Yz.Core.Tools;

namespace Yz.FileService.Middlewares
{
    /// <summary>
    /// 合并文件
    /// </summary>
    public class MergeMiddleware : BaseUploadMiddleware, IMiddleware
    {
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            context.Response.ContentType = "application/json; charset=utf-8";
            #region 跨域上传
            if (context.Request.Method.Equals(HttpMethods.Options, StringComparison.OrdinalIgnoreCase))
            {
                base.AddHttpOptionHeader(context);
            }
            #endregion

            #region 后台post上传
            else if (context.Request.Method.Equals(HttpMethods.Post, StringComparison.OrdinalIgnoreCase))
            {
                try
                {
                    #region 验证token
                    await ValidateTokenAsync(context);
                    context.Request.Headers.TryGetValue("appId", out StringValues appId);
                    #endregion

                    #region 文件验证
                    var requestReader = new StreamReader(context.Request.Body);
                    var requestContent = await requestReader.ReadToEndAsync();
                    ParaMergeFile mergeFile = new ParaMergeFile();      //获取参数 
                    if (!string.IsNullOrEmpty(requestContent))
                    {
                        mergeFile = JsonConvert.DeserializeObject<ParaMergeFile>(requestContent);
                        if (mergeFile == null)
                        {
                            await context.Response.WriteAsync(new VmUpFileBase()
                            {
                                msg = "文件无效！"
                            }.ToJson());
                            return;
                        }
                    }
                    if (mergeFile == null || string.IsNullOrEmpty(mergeFile.FileName) || mergeFile.FileName.IndexOf(".") <= 0 || string.IsNullOrEmpty(mergeFile.Guid) || mergeFile.Chunks < 1)
                    {
                        await context.Response.WriteAsync(new VmUpFileBase()
                        {
                            msg = "文件合并信息不正确"
                        }.ToJson());
                        return;
                    }
                    //后缀验证
                    var ext = Path.GetExtension(mergeFile.FileName).ToLower();
                    var fileLimit = _uploadConfig.Limits.Where(p => p.Value.AllowExts.Contains(ext)).FirstOrDefault();
                    if (string.IsNullOrEmpty(ext) || string.IsNullOrEmpty(fileLimit.Key))
                    {
                        await context.Response.WriteAsync(new VmUpFileBase()
                        {
                            msg = "不支持此文件类型！"
                        }.ToJson());
                        return;
                    }
                    ///判断是否分片
                    if (!fileLimit.Value.IsChunk)
                    {
                        await context.Response.WriteAsync(new VmUpFileBase()
                        {
                            msg = "此文件类型不支持分片上传"
                        }.ToJson());
                        return;
                    }
                    #endregion
                    FileType fileType = FileType.None;
                    if (FileTypeList.ImgList.Contains(ext))
                    {
                        fileType = FileType.Pic;
                    }
                    else if (FileTypeList.DocList.Contains(ext))
                    {
                        fileType = FileType.Doc;
                    }
                    else if (FileTypeList.VdoList.Contains(ext))
                    {
                        fileType = FileType.Vdo;
                    }
                    else if (FileTypeList.RarList.Contains(ext))
                    {
                        fileType = FileType.Rar;
                    }
                    else if (FileTypeList.RdoList.Contains(ext))
                    {
                        fileType = FileType.Rdo;
                    }
                    var fileSize = await MergeChunkFiles(appId, mergeFile);
                    await context.Response.WriteAsync(new VmUpFile()
                    {
                        suc = true,
                        File = new FileUp()
                        {
                            Id = fileSize.Path.Replace(_uploadConfig.VirtualPath, "").ToDes3Encrypt(),
                            Path = fileSize.Path,
                            Name = mergeFile.FileName,
                            FileSuffix = ext,
                            FileType = fileType,
                            Size = fileSize.Size
                        },
                        msg = "文件合并成功！"
                    }.ToJson());

                }
                catch (Exception ex)
                {
                    YzNLog.Error(ex);
                    await context.Response.WriteAsync(new VmUpFileBase()
                    {
                        msg = "文件合并失败"
                    }.ToJson());
                }
            }
            #endregion

            #region 非法上传
            else
            {
                await base.AddHttpNotAllowedAsync(context);
            }
            #endregion 
        }

        /// <summary>
        /// 合并文件
        /// </summary> 
        /// <param name="ext"></param>
        /// <param name="chunkFiles"></param>
        /// <returns></returns>
        private async Task<FileSize> MergeChunkFiles(string appId, ParaMergeFile mergeFile)
        {
            string[] chunkFiles = Directory.GetFiles(Path.Combine(_uploadConfig.PhysicalPath, appId, tempFolder, mergeFile.Guid), yzTmpFile + ".*", SearchOption.TopDirectoryOnly);

            var dtNow = DateTime.Now;
            var folderPath = "/" + appId + "/" + dtNow.ToString("yyyy") + "/" + dtNow.ToString("MM") + "/" + dtNow.ToString("dd") + "/";
            var localFolderPath = Path.Combine(_uploadConfig.PhysicalPath, folderPath);
            if (!Directory.Exists(localFolderPath))
            {
                Directory.CreateDirectory(localFolderPath);
            }
            var ext = Path.GetExtension(mergeFile.FileName).ToLower();
            var fileNewName = Guid.NewGuid().ToString("n") + ext;
            var filePath = Path.Combine(localFolderPath, fileNewName);
            long fileSize = 0;
            using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
            {
                foreach (var chunkFile in chunkFiles.OrderBy(x => int.Parse(x.Substring(x.LastIndexOf(".") + 1))))
                {
                    using (var chunkStream = File.OpenRead(chunkFile))
                    {
                        await chunkStream.CopyToAsync(fileStream);
                    }
                    //是否要删除块
                    File.Delete(chunkFile);
                }
                fileSize = fileStream.Length;
            }
            return new FileSize()
            {
                Path = _uploadConfig.VirtualPath + folderPath + fileNewName,
                Size = fileSize
            };
        }

    }
}
